#include "DSkillData.j"

// 系统级技能，每个图都能用的那种，英雄D跳等
// @author:wangff8@qq.com @date:2024-02-29
library DSkill initializer init requires PropertyUtil, DSkillData

    globals
        // 最远距离
        real array d_max_distance
    endglobals

    // ==================== 当玩家按下D跳触发
    // 移动位置计时器
    function timer_movePosition takes nothing returns nothing

        local timer t = GetExpiredTimer()
        local integer tid = GetHandleId(t)
        
        // 每次移动距离
        local real tyjl = 80
        local unit u = LoadUnitHandle(gameht, tid, 1)
        local integer uid = GetPlayerId(GetOwningPlayer(u))

        // 要位移的角度
        local real angle = LoadReal(gameht, tid, 4)
        // 计算出要移动的位置
        local real x = GetUnitX(u) + tyjl * CosBJ(angle) 
        local real y = GetUnitY(u) + tyjl * SinBJ(angle)
        // 移动的次数
        local integer count = LoadInteger(gameht, tid, 2) + 1
        // 跳跃特效
        local effect ect = LoadEffectHandle(gameht, tid, 3)

        // 原始位置（用来计算距离是否达到
        local real ysX = LoadReal(gameht, tid, 5)
        local real ysY = LoadReal(gameht, tid, 6)
        // 实际要跳跃的距离
        local real distance1 = LoadReal(gameht, tid, 7)
        // 计算已经跳跃的距离
        local real distance2 = SquareRoot((x - ysX) * (x - ysX) + (y - ysY) * (y - ysY))

        // 增加次数
        call SaveInteger(gameht, tid, 2, count)

        // 判断阻隔
        if (distance2 >= distance1) or (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) or (count >= 10) or (GetUnitState(u, UNIT_STATE_LIFE) <= 1.00) then
            // 打开碰撞
            call SetUnitPathing( u, true )
            // 删除特效
            call DestroyEffect(ect)
        else
            // 表示可以移动
            call SetUnitPosition(u, x, y)
            call SetUnitFacing(u, angle)

            // 显示阴影
            set x = GetUnitX(u) + (tyjl/2.0) * CosBJ(angle) 
            set y = GetUnitY(u) + (tyjl/2.0) * SinBJ(angle)
            call showShadowUnit(uid, count, x, y, angle)

        endif
        
        // 隐藏
        call setShadowUnitAlpha(uid, count - 5, 60.0)
        call hideShadowUnit(uid, count - 10)
        if count >= 25 then
            // 删除计时器
            call DestroyTimer(t)
            call FlushChildHashtable(gameht, tid)
        endif

        set t = null
        set u = null
        set ect = null
    endfunction


    // 播放动作
    private function playAnimation takes nothing returns nothing

        local timer t = GetExpiredTimer()
        local integer tid = GetHandleId(t)
        local unit u = LoadUnitHandle(gameht, tid, 1)

        call SetUnitAnimation( u, "Attack" )
        call SetUnitAnimation( u, "Spell Slam" )

        call DestroyTimer( t )
        call FlushChildHashtable( gameht, tid )

        set u = null
    endfunction

    // 跳跃 x y 为跳跃的坐标  该跳跃函数为D跳专属，如需封装可参考次方法
    private function jump takes unit u, real jumpX, real jumpY returns nothing
        local integer uid = GetPlayerId(GetOwningPlayer(u))
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local timer t
        local integer tid
        // 角度
        local real angle = bj_RADTODEG * Atan2(jumpY - y, jumpX - x)
        // 距离
        local real distance = SquareRoot((jumpX - x) * (jumpX - x) + (jumpY - y) * (jumpY - y))
        local effect ect
        local real tempX
        local real tempY

        // 规定最大距离为700
        if distance > d_max_distance[uid] then
            set distance = d_max_distance[uid]
        endif

        // 播放位移动作
        set t = CreateTimer()
        set tid = GetHandleId(t)
        call SaveUnitHandle(gameht, tid, 1, u)
        call TimerStart(t, 0, true, function playAnimation)

        call SetUnitPathing( u, false )
        call EXSetUnitFacing( u, angle )
        // 设置特效
        set tempX = x + ( distance * 0.70 * CosBJ(angle) )
        set tempY = y + ( distance * 0.70 * SinBJ(angle) )
        set ect = AddSpecialEffect("war3mapImported\\D_CF.mdx", tempX, tempY)
        call EXEffectMatRotateZ( ect, GetUnitFacing(u) - 180.0 )
        call EXSetEffectSize( ect, 0.40 )

        // 移动位置计时器
        set t = CreateTimer()
        set tid = GetHandleId(t)
        call SaveUnitHandle(gameht, tid, 1, u)
        call SaveEffectHandle(gameht, tid, 3, ect)
        call SaveReal(gameht, tid, 4, angle)
        call SaveReal(gameht, tid, 5, x)
        call SaveReal(gameht, tid, 6, y)
        call SaveReal(gameht, tid, 7, distance)
        call TimerStart(t, 0.02, true, function timer_movePosition)

        set t = null
        set ect = null
    endfunction

    // 同步D函数
    private function syncD takes nothing returns nothing
        local integer uid = GetPlayerId(DzGetTriggerSyncPlayer())
        local string data = DzGetTriggerSyncData()
        local string strXY
        local string strX
        local string strY
        local integer loopi

        if FF_GetHp(udg_player_select_hero[uid]) < 1 then
            set data = null
            set strXY = null
            set strX = null
            set strY = null
            return 
        endif

        // 截取出鼠标的XY坐标
        set strXY = SubString(data, 1, StringLength(data))
        set loopi = 1
        loop
            exitwhen loopi > StringLength(strXY)
            if SubString(strXY, loopi - 1, loopi) == "/" then
                set strX = SubString(strXY, 0, loopi - 1)
                set strY = SubString(strXY, loopi, StringLength(strXY))
                call DoNothing() YDNL exitwhen true//(  )
            endif
            set loopi = loopi + 1
        endloop

        // 跳跃
        call jump(udg_player_select_hero[uid], S2R(strX), S2R(strY))

        // call BJDebugMsg(strXY)
        // call BJDebugMsg(strX)
        // call BJDebugMsg(strY)
    endfunction

    // 异步执行D函数
    private function execD takes nothing returns nothing

        local integer uid = GetPlayerId(DzGetTriggerKeyPlayer())
        call DzSyncData( "Jump", ( I2S(uid) + I2S(R2I(DzGetMouseTerrainX())) + "/" + I2S(R2I(DzGetMouseTerrainY())) ) )
    endfunction

    // 初始化注册
    private function initDTrig takes nothing returns nothing

        local trigger tri = CreateTrigger()

        call DzTriggerRegisterSyncData( tri, "Jump", false )
        call TriggerAddCondition(tri, Condition(function syncD))
        
        if GetLocalPlayer() == GetLocalPlayer() then
            // 点击
            call DzTriggerRegisterKeyEventByCode( null, 'D', 1, false, function execD)
            // 释放
            // call DzTriggerRegisterKeyEventByCode( null, 'D', 0, false, function execD)
        endif
        set tri = null
    endfunction

    private function init takes nothing returns nothing
        local integer uid = 0
        loop
            exitwhen uid > PLAYER_NUMBER
            set d_max_distance[uid] = 700.0
            set uid = uid + 1
        endloop


        call initDTrig()
    endfunction
endlibrary
